package com.patternity.annotation.util;

import java.io.File;

/**
 * 
 */

/**
 * A writes Java annotations into files
 * 
 * @author Cyrille.Martraire
 */
public class AnnotationWriter {

	protected static final String COMMENT_OPEN = "/*";

	protected static final String COMMENT_JAVADOC_OPEN = "\n/**";

	protected static final String COMMENT_LINE = "\n * ";

	protected static final String COMMENT_CLOSE = "\n */";

	protected static final String ANNOTATION_DECLARE = "\npublic @interface ";

	protected static final String ANNOTATION_OPEN = " {";

	protected static final String ANNOTATION_CLOSE = "\n}";

	protected static final String DOCUMENTED = "\n@Documented";

	protected static final String DOCUMENTED_IMPORT = "\nimport java.lang.annotation.Documented;";

	protected static final String RETENTION = "\n@Retention(RetentionPolicy.";

	protected static final String RETENTION_IMPORT = "\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;";

	protected static final String TARGET = "\n@Target({ ElementType.METHOD, ElementType.TYPE })";

	protected static final String TARGET_IMPORT = "\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Target;";

	private StringBuilder sb = new StringBuilder();

	public void reset() {
		sb = new StringBuilder();
	}

	public void imports() {
		sb.append(RETENTION_IMPORT);
		sb.append(TARGET_IMPORT);
		sb.append(DOCUMENTED_IMPORT);
	}

	public void openJavadoc() {
		sb.append(COMMENT_JAVADOC_OPEN);
	}

	public void blankLine() {
		sb.append("\n");
	}

	public void addComment(final String comment) {
		sb.append(COMMENT_LINE);
		sb.append(comment);
	}

	public void addLink(final String link, final String linkLabel,
			final String label) {
		sb.append(COMMENT_LINE);
		sb.append(COMMENT_LINE);
		sb.append("@see <nobr><a href=\"" + link + "\">" + linkLabel + "</a>"
				+ label + "</nobr>");
	}

	public void addLink(final String link, final String label) {
		sb.append(COMMENT_LINE);
		sb.append(COMMENT_LINE);
		sb.append("@see <a href=\"" + link + "\">" + label + "</a>");
	}

	public void closeJavadoc() {
		sb.append(COMMENT_CLOSE);
	}

	public void declarePackage(final String packageName) {
		sb.append("package ");
		sb.append(packageName);
		sb.append(";");
	}

	public void metaAnnotations(final String retention, final boolean documented) {
		sb.append(RETENTION);
		sb.append(retention.toUpperCase());
		sb.append(")");
		if (documented) {
			sb.append(DOCUMENTED);
		}
	}

	public void declare(final String annotationName) {
		sb.append(ANNOTATION_DECLARE);
		sb.append(annotationName);
		sb.append(ANNOTATION_OPEN);
	}

	public void attribute(final String type, final boolean multiple,
			final String name, final String defaultValue) {
		sb.append("\n\n\t");
		sb.append(type);
		if (multiple) {
			sb.append("[]");
		}
		sb.append(" ");
		sb.append(name);
		sb.append("()");
		if (defaultValue != null) {
			sb.append(" default ");
			sb.append(defaultValue);
		}
		sb.append(";");
	}

	public void attribute(final String typeSpaceName) {
		sb.append("\n\n\t");
		sb.append(typeSpaceName);

		final boolean multiple = typeSpaceName.indexOf("[]") != -1;

		sb.append("()");
		if (multiple) {
			sb.append(" default ");
			sb.append("{}");
		} else {
			// sb.append("\"\"");
		}
		sb.append(";");
	}

	public void close() {
		sb.append(ANNOTATION_CLOSE);
	}

	public final static File pathToFile(final String output,
			final String packageName, final String category) {
		final String fullPkg = packageName + "." + category.toLowerCase();
		return new File(output + "/" + fullPkg.replace('.', '/'));
	}

	@Override
	public String toString() {
		return sb.toString();
	}

}
